home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i052: uucp 1.03D - unix compatible uucp/mail/news system, Part08/16
- Message-ID: <11291@xanth.cs.odu.edu>
- Date: 4 Feb 90 02:36:14 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: overload!dillon (Matt Dillon)
- Lines: 1948
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
-
- Submitted-by: overload!dillon (Matt Dillon)
- Posting-number: Volume 90, Issue 052
- Archive-name: unix/uucp-1.03d/part08
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 8 (of 16)."
- # Contents: SlowSetup.DOC src/dmail/load_mail.c src/uucico/gio.c
- # Wrapped by tadguy@xanth on Sat Feb 3 20:51:14 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'SlowSetup.DOC' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'SlowSetup.DOC'\"
- else
- echo shar: Extracting \"'SlowSetup.DOC'\" \(14853 characters\)
- sed "s/^X//" >'SlowSetup.DOC' <<'END_OF_FILE'
- X
- X SLOWSETUP.DOC
- X
- X Matthew Dillon
- X 891 Regal Rd.
- X Berkeley, Ca. 94708
- X
- X pacbell.PacBell.COM!sorinc!overload!dillon
- X
- X
- X GETTING UUCP UP AND RUNNING FOR REAL
- X
- X
- X This UUCP distribution in general is not for the uninitiated. That is,
- X it is not user friendly. This particular document outlines a general
- X installation procedure. Be warned that there are a LOT of things you
- X will have to do to bring up UUCP on your machine.
- X
- X This document shows a TYPICAL setup. You will most likely want to
- X modify the example to fit your own needs. I cover all the points
- X though.
- X
- X (1) You made backups of the distribution floppies, right? DO NOT
- X MODIFY THE DISTRIBUTION FLOPPIES. The instructions below are
- X long and some are complex and you may wish to refer to the
- X original distribution diskettes if you accidently mess something
- X up.
- X
- X
- X (2A) Installing UUCP on a single floppy system.
- X
- X Well, it *is* possible, but difficult. you need to make as much
- X space as possible available on the main floppy.
- X
- X The second distribution disk contains only the source and manual
- X pages. I suggest you shuffle things around a bit. You already
- X have a copy of the first distribution diskette. I suggest you
- X format a new disk and put the MAN directory of the second
- X distribution disk on it. Note that there is a MAN directory
- X on the boot disk as well but this one contains only dmail.help
- X which you need to gain online help from dmail.
- X
- X The following executables are required on the boot floppy and
- X should not be moved off. You should move as many of the remaining
- X executables somewhere else as you can.
- X
- X Required Executables in C
- X
- X c/dmail
- X c/getty
- X c/rmail
- X c/uucico
- X c/rnews
- X c/uucp
- X c/unbatcher
- X c/dme (unless you configure your own editor)
- X c/sendmail
- X c/uux
- X c/uuxqt
- X
- X You will want to change the ASSIGNments in s/startup-sequence
- X as follows:
- X
- X Assign UUSPOOL: UUCP:SPOOL
- X Assign UUMAIL: UUCP:MAIL
- X Assign UUNEWS: UUCP:MAIL/NEWS
- X
- X These directories MUST be in nonvoltile storage or your USENET
- X node will be unreliable.
- X
- X (2B) Installing UUCP on a duel floppy system.
- X
- X In this case very little shuffling is required. I suggest
- X the second floppy be used for UUSPOOL:, UULIB:, UUMAIL:, UUNEWS:,
- X GETTY:, and UUPUB:.
- X
- X Format a new floppy (this will be your second floppy) and create
- X directories as follows:
- X
- X MakeDir df1:spool
- X MakeDir df1:mail
- X MakeDir df1:mail/news
- X MakeDir df1:pub
- X MakeDir df1:lib
- X
- X Modify the Assignments in s/startup-sequence of the boot floppy
- X as follows:
- X
- X Assign UUSPOOL: df1:spool
- X Assign UULIB: df1:lib
- X Assign UUMAIL: df1:mail
- X Assign UUNEWS: df1:mail/news
- X Assign GETTY: UULIB:
- X Assign UUPUB: df1:pub
- X
- X Copy df0:lib to df1:lib and either delete or rename df0:lib to
- X prevent confusion. What we have done is move all dynamic storage
- X to df1: .. files that will change a lot or require a lot of disk
- X space. Specifically, UULIB: was moved to DF1: because the
- X sequence number file is kept in UULIB: and this is updated for
- X each mail message sent.
- X
- X (2B) Installing UUCP on a Hard Drive
- X
- X Make a directory called UUCP on your hard drive somewhere. And
- X Assign UUCP: to it. Copy the contents of both distribution
- X floppies to your harddrive:
- X
- X (put first disk in DF0:)
- X 1> Copy df0: UUCP: ALL CLONE
- X (put second disk in DF0:)
- X 1> Copy df0: UUCP: ALL CLONE
- X
- X It is easiest to keep all the directories in one place. Note
- X that a MAN directory exists on both distribution floppies, simply
- X merge them together.
- X
- X Merge the startup-sequence on the boot floppy into your master
- X startup-sequence. Make sure you get all the Assigns and that
- X they are properly reassigned to the appropriate directory on
- X the harddisk. Most people normally make a master UUCP: assign
- X as a reference point to other assigns.
- X
- X
- X Be sure that UUSPOOL:, UUMAIL:, UUNEWS: and UUPUB: are assigned
- X to your hard disk instead of ram.
- X
- X You will most likely want to run DCron and Getty from your
- X startup-sequence. Be sure that UUCP:C is assigned *before*
- X these programs are run so they pick up the appropriate path.
- X
- X If Getty interferes with any terminal program you might use
- X you may be forced to BREAK it. Remember to restart it to
- X enable incomming UUCP calls again.
- X
- X DCron is an extremely useful utility to run, especially in
- X systems with hard disks. The only thing you have to watch out
- X for is to be sure to BREAK it (kill it) before shutting off your
- X machine. DCron writes to its log file and runs other programs
- X based on the date and you don't want to accidently turn off your
- X machine when DCron has just started up some other program that
- X may write to your hard disk.
- X
- X In the context of UUCP, DCron is normally used to automatically
- X poll systems in the wee hours while you are asleep, to trim
- X log files automagically, and maybe disable the modem's speaker
- X while you are asleep (at least, that is what I use it for).
- X
- X Most people with HDs running UUCP leave their Amiga's on 24 hours
- X a day.
- X
- X Other System Directories
- X
- X Merge the mountlist into your master mountlist and copy any
- X devices from l that you do not already have into your
- X master l directory.
- X
- X merge or copy uucp:s/crontab to s:crontab and uucp:s/.edrc to
- X s:.edrc .
- X
- X You can ignore files in uucp:system, they are standard system
- X files.
- X
- X ---- -- - - - - - - -- ----
- X
- X (3) Other startup-sequence efficiency considerations
- X
- X UUCP relies heavily on the Amiga's multitasking capabilities.
- X Most programs execute other programs. Many programs in UUCP:C
- X may be made resident as shown by the pure bit being set. You
- X will probably at least want to make C:RUN resident if you haven't
- X already.
- X
- X Depending on available RAM you may want to make certain other
- X progams resident. Here are some suggestions:
- X
- X uucp:c/dme ; run by dmail to edit mail
- X uucp:c/uuxqt ; run by uucico to handle received files
- X uucp:c/rmail ; run by uuxqt to handle received mail
- X uucp:c/sendmail ; run by dmail to handle outgoing mail
- X
- X (note that uucp:c/sendmail and uucp:c/rmail are the same
- X executable just renamed)
- X
- X STACK: All programs should run with a stack of 8192. This
- X has been tested for all programs except RNews and ANews which
- X may require more.
- X
- X RNEWS: RNews currently takes a huge amount of memory and
- X will run only on machines with at least 1.5MB of ram. Even
- X with 1.5MB you may need to run rnews manually instead of having
- X it automatically run by uuxqt. In this case rename the rnews
- X executable to something else and create a dummy script file
- X in its place (named as 'rnews') with the script bit set.
- X
- X (4) System requirements
- X
- X Be sure you are running at least version 1.3 of the operating
- X system. The main consideration is that you are using at least
- X the 1.3 serial device.
- X
- X The NULL: device is required, this is in the l directory of
- X the boot floppy as already discussed.
- X
- X The UUSER: device is not required unless you want to start
- X getting fancy with the Getty. This is mainly a programmer's
- X tool.
- X
- X (5) Getty
- X
- X Normally one runs a Getty in his startup-sequence on the internal
- X serial port (from which you wish to receive calls). Currently
- X only one Getty may be run PER SERIAL DEVICE NAME, and using other
- X units of a given serial device will interfere with Getty's operation.
- X This is due to the difficulty of implementation in Getty and will
- X eventually be fixed (to fix the problem I have to patch into
- X the OpenDevice and CloseDevice vectors).
- X
- X So for now you can really only run Getty on the internal serial
- X device.
- X
- X Getty does its best to not interfere with comm programs and
- X the like, but if a comm program refuses to run because it
- X can't get exclusive access to the serial port you may have
- X to kill the Getty by BREAKing it from a CLI.
- X
- X Refer to the manual page MAN:Getty for more information (for
- X floppy based systems all manual pages are on the second
- X distribution diskette).
- X
- X (6) SHELL-STARTUP
- X
- X Assuming you are using the 1.3 Shell, the S:Shell-Startup file
- X normally contains at least a Path command and Stack command to
- X properly setup a newshell's path and stack. Be sure the stack is
- X at least 8192 for this distribution of UUCP and add the UUCP:C (or
- X wherever you have placed the distribution executables) to your path
- X list. Older UUCP distributions required a huge stack, this has
- X been fixed.
- X
- X (7) SITE-SETUP CONTROL FILES
- X
- X The following is a description of control and log files required
- X for UUCP and how you must modify them to install your system.
- X
- X (GETTY: is normally Assign'd to UULIB:)
- X
- X GETTY:Getty-Header
- X
- X This file contains the header line that is printed before a
- X login: prompt and is typically only two or three lines long.
- X The header usually contains your node name and the version of
- X the OS you are running under so people calling from term
- X programs know who you are.
- X
- X (Getty can be used to run things other than uucico)
- X
- X Modify accordingly.
- X
- X GETTY:Passwd
- X
- X The password file is used by Getty to authenticate login
- X requests. In the context of UUCP, remote UUCICOs that call
- X your machine up will provide a login and password. Getty
- X handles this and if the login is valid and the password matches
- X will run the appropriate program found in the password file.
- X
- X Getty also deals with such features as automatic disconnect on
- X timeout and logs times for all incomming and outgoing calls.
- X
- X In a serious system you should first remove all the junk
- X entries that come with the distribution. You need an entry
- X for each remote machine you want to be able to call you. You
- X do not necessarily need to give them logins that corrospond to
- X their machine names though this is how it is usually done.
- X
- X Other programs in the future will be able to be run from
- X a Getty.
- X
- X Later versions of UUCP will implement MAILER-DAEMON type
- X stuff like 'unknown user', in which case the password file
- X will be used to define which user names are valid on the
- X system.
- X
- X GETTY:LOGFILE
- X
- X The logfile is appended to by Getty whenever an incomming
- X call occurs or somebody takes over the serial port. It
- X logs connect and disconnect times for incomming calls and
- X usage for external programs.
- X
- X UULIB:Domain
- X
- X In nearly every case you will not need this file.
- X
- X Those of you who wish to do domain routing through
- X their machine or have more than one default for
- X unknown destinations should refer to the manual
- X page MAN:Domains.
- X
- X UULIB:.Signature
- X
- X .Signature is used by the Mail program and normally appended
- X to outgoing mail.
- X
- X Modify accordingly.
- X
- X UULIB:Seq
- X
- X The Seq file should exist but otherwise not be modified by
- X the user (except for setting it to a "1" once a year). This
- X file is atomically updated and used to provide unique filenames
- X and mail IDs for outgoing mail.
- X
- X UULIB:Security
- X
- X This file contains a list of allowed directories remote UUCP
- X transfers may read and write to. Refer to the Security manual
- X page. This file never contains the UUSPOOL: directory which
- X is implicitly read-write.
- X
- X You need not modify this file now but should keep it in mind.
- X It protects your system in as much as I have been able to
- X close the loopholes. Loopholes might still exist.
- X
- X UULIB:news.distribution
- X
- X This file contains a list of news distribution idents for
- X various areas and must normally be modified according to
- X where you are.. you need to be a UUCP guru to do this. Most
- X people can just leave it alone.
- X
- X UULIB:Config
- X
- X This file contains configuration information for many
- X executables in UUCP:C and should be modified accordingly.
- X
- X Be sure you modify at least the following entries. REFER TO
- X THE 'Assigns' MANUAL PAGE.
- X
- X NodeName
- X UserName
- X RealName
- X NewsFeed (not required if you don't care about news)
- X Organization
- X TimeZone
- X DefaultNode
- X
- X **** Take some time to pick a node name for yourself. It
- X should be no more than 8 characters long. Some UUCP sites
- X barf at node names longer than 6 chars so if you are not
- X sure of your neighbors pick one no more than 6 characters
- X long. Your site name should be in lower case.
- X
- X UULIB:L.Sys
- X
- X This file contains site information for sites that may call
- X you up or you may call up.
- X
- X You must modify this file appropriately before you can run UUCP,
- X refer to the 'L.Sys' manual page.
- X
- X UULIB:Aliases
- X
- X This is a mail aliases file with aproximately the same
- X power as /usr/lib/aliases on UNIX systems. You should
- X refer to the 'Aliases' manual page and modify this file as
- X appropriate for various defaults like 'postmaster'... to
- X whatever user name you pick for yourself.
- X
- X UUCP:S/Crontab
- X
- X This is a functional Crontab file for use with the DCron program.
- X This file is normally moved to S: (it is useless in UUCP:S).
- X
- X UUSPOOL:LOGFILE
- X
- X UUCICO and other programs log errors and other things to
- X this file. Normally you use DCron to clean up this and
- X other log files once daily to keep them from getting to large.
- X
- X
- X (8) TESTING / DMAIL
- X
- X You will next want to test your UUCP configuration. If testing
- X with a friend's Amiga running the same distribution simply
- X email to him, then one of you run uucico -s<remotesystem>
- X just like in QuickSetup.DOC, except this time you are using
- X the system name he picked instead of 'test1' or 'test2'.
- X
- X If the initial tests in QuickSetup.DOC worked and the system
- X is not working now check the following (common problems):
- X
- X (a) the login and password in your L.Sys file (that uucico uses
- X to login to the remote machine) matches the login and
- X password in the remote machine's Getty:Passwd file.
- X
- X (b) There is an entry for your node in the remote machine's
- X L.Sys file and vise versa
- X
- X (c) The telephone number is correct
- X
- X (d) the node names are all in lower case
- X
- X (e) you constructed the email address correctly (nodename!user)
- X
- X I suggest you get UUCP running with a friend before getting it
- X running with a UNIX system as it is easier to test it with a
- X friend.
- X
- X Assuming you email to the user name he picked for his UULIB:Config
- X 'UserName' entry and he did the same thing to you, entering
- X 'dmail' without any arguments will bring up the mail shell
- X and allow you to read the message after transfer via UUCico
- X is complete. You can check that the email actually arrived
- X into the right mail box in UUMAIL: by simply getting a directory
- X of UUMAIL:
- X
- X READ the manual page for DMail for information on the
- X construction of mail paths to other systems and users.
- X
- X
- END_OF_FILE
- if test 14853 -ne `wc -c <'SlowSetup.DOC'`; then
- echo shar: \"'SlowSetup.DOC'\" unpacked with wrong size!
- fi
- # end of 'SlowSetup.DOC'
- fi
- if test -f 'src/dmail/load_mail.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/dmail/load_mail.c'\"
- else
- echo shar: Extracting \"'src/dmail/load_mail.c'\" \(13593 characters\)
- sed "s/^X//" >'src/dmail/load_mail.c' <<'END_OF_FILE'
- X
- X/*
- X * LOAD_MAIL.C
- X *
- X * (C) Copyright 1985-1990 by Matthew Dillon, All Rights Reserved.
- X *
- X * file-io routines to scan the mail file and load required information.
- X *
- X *
- X * Global Routines: HOLD_LOAD() hold on loading mail after change
- X * NOHOLD_LOAD() hold off.. load if changes
- X * LOAD_CHANGES() reload mail if changed
- X * LOAD_MAIL() load/reload mail
- X * SAVE_FILE() save mail items back to spool
- X * CHECK_NEW_MAIL() check for new mail
- X * WRITE_FILE() append mail items to a file
- X * GET_EXTRA_OVR() ret index of Field (create if not)
- X * ADD_EXTRA() add another field (reloads mail)
- X * DELETE_EXTRA() delete a field
- X * GET_EXTRA() ret index of Field, or error
- X * M_SELECT() select on current message list
- X *
- X *
- X * Static Routines: LOAD_HASH() load hash table from fields list
- X * FREE_ENTRY() unload EVERYTHING
- X * FREE_TABLE() unload all Fields table
- X * LOAD_FILE() raw file loading/counting
- X *
- X *
- X */
- X
- X#include <stdio.h>
- X#include <sys/file.h>
- X#include "dmail.h"
- X
- Xvoid do_flock();
- Xvoid free_table();
- Xvoid load_hash();
- X
- X#define NOHOLD 0
- X#define HOLD 1
- X
- X#define NO_BASE 0
- X#define NO_FIELDS 1
- X#define ENTRY_OK 2
- X
- Xstruct FIND Find[MAXTYPE + 1] = {
- X "From:" , 5, 1, 0,
- X "To:" , 3, 1, 0,
- X "Subject:", 8, 1, 0 };
- X
- Xstatic int File_size;
- Xstatic int changed, load_hold;
- Xstatic int Hash[256];
- X
- Xstatic char *quo_quo = "";
- X
- Xvoid
- Xhold_load()
- X{
- X load_hold = 1;
- X}
- X
- Xvoid
- Xnohold_load()
- X{
- X void load_changes();
- X load_hold = 0;
- X load_changes();
- X}
- X
- Xvoid
- Xload_changes()
- X{
- X if (changed && !load_hold)
- X load_mail(Entries, 1);
- X}
- X
- Xinitial_load_mail()
- X{
- X if (load_mail (0, 0) < 0)
- X return (-1);
- X return ((Entries) ? 1 : -1);
- X}
- X
- X
- Xstatic
- Xload_mail(at, from0)
- X{
- X FILE *fi;
- X int i, count, file_size;
- X
- X if (No_load_mail)
- X return (-1);
- X push_break();
- X load_hash();
- X if (from0)
- X free_table (0, HOLD);
- X else
- X free_table (at, NOHOLD);
- X fi = fopen (mail_file, "r+");
- X if (m_fi != NULL)
- X fclose (m_fi);
- X m_fi = fopen (mail_file, "r+");
- X if (fi == NULL || m_fi == NULL) {
- X pop_break();
- X return (-1);
- X }
- X do_flock (fileno(m_fi), LOCK_EX);
- X if (at)
- X fseek (fi, Entry[at].fpos, 0);
- X else
- X fseek (fi, 0, 0);
- X count = Entries;
- X while (search_from(fi))
- X ++count;
- X if (Entries != count) {
- X if (!lmessage_overide)
- X printf ("%d Other Items loaded\n", count - Entries);
- X lmessage_overide = 0;
- X Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1));
- X bzero (&Entry[Entries], sizeof(*Entry) * (count + 1 - Entries));
- X }
- X Entries = count;
- X for (i = at; i < Entries; ++i)
- X Entry[i].no = Entry[i].status = 0;
- X Entry[i].fpos = File_size = file_size = ftell (fi);
- X fclose (fi);
- X load_file ((from0) ? 0 : at);
- X if (file_size != File_size) { /* Last entry incomplete? */
- X free_table (Entries - 1, NOHOLD);
- X }
- X changed = 0;
- X flock (fileno(m_fi), LOCK_UN);
- X pop_break();
- X return (1);
- X}
- X
- Xvoid
- Xdo_flock(fd, stat)
- X{
- X if (flock(fd, stat | LOCK_NB) < 0) {
- X puts ("File in use, Waiting for lock");
- X flock (fd, stat);
- X puts ("Have lock");
- X }
- X}
- X
- Xstatic
- Xload_file(at)
- Xint at;
- X{
- X FILE *fi;
- X char *next, *ptr;
- X int i, bit, maxbit, len, count, havefrom;
- X
- X maxbit = 0;
- X for (i = 0; Find[i].search != NULL; ++i)
- X maxbit = (maxbit << 1) | 1;
- X fi = fopen (mail_file, "r");
- X count = -1;
- X havefrom = 0;
- X while (havefrom || search_from (fi)) {
- X havefrom = 0;
- X if (++count >= Entries)
- X break;
- X len = strlen(Buf) - 1;
- X Buf[len] = '\0';
- X next = next_word(Buf);
- X len -= next - Buf;
- X Entry[count].fpos = ftell (fi);
- X Entry[count].from = malloc (len + 1);
- X bcopy (next, Entry[count].from, len + 1);
- X
- X /* SEARCH FIELD LIST */
- X
- X bit = 0;
- X if (XDebug)
- X printf ("No %d ---------------------\n", count + 1);
- X while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
- X if (Buf[0] == '\n')
- X break;
- X if (isfrom(Buf)) {
- X havefrom = 1;
- X break;
- X }
- X len = strlen(Buf) - 1;
- X Buf[len] = '\0';
- X if (XDebug)
- X printf ("CHECK: %s\n", Buf);
- X next = next_word(Buf);
- X len -= next - Buf;
- X if (Hash[*Buf] == 0)
- X continue;
- X if (Hash[*Buf] > 0) {
- X i = Hash[*Buf] & 0xff;
- X if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
- X goto found;
- X continue;
- X }
- X for (i = -Hash[*Buf] & 0xff; Find[i].search; ++i) {
- X if (*Find[i].search != *Buf)
- X break;
- X if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
- X goto found;
- X }
- X continue;
- Xfound:
- X if (XDebug)
- X printf ("Found: %d %s\n", i, Buf);
- X if (Find[i].notnew == 0) {
- X Find[i].notnew = 1;
- X ptr = Buf;
- X while (*ptr && *ptr != ':')
- X ++ptr;
- X ++ptr;
- X Find[i].search =
- X realloc (Find[i].search, ptr - Buf + 1);
- X strncpy (Find[i].search, Buf, ptr - Buf);
- X *(Find[i].search + (ptr - Buf)) = '\0';
- X Find[i].len = strlen(Find[i].search);
- X }
- X compile_field (Buf, fi);
- X Entry[count].fields[i] =
- X malloc (strlen(next) + 1);
- X strcpy (Entry[count].fields[i], next);
- X if ((bit |= (1 << i)) == maxbit)
- X break;
- X }
- X if (bit != maxbit) {
- X for (i = 0; Find[i].search != NULL; ++i) {
- X if (((1 << i) & bit) == 0) {
- X Entry[count].fields[i] = quo_quo;
- X }
- X }
- X }
- X }
- X File_size = ftell (fi);
- X fclose (fi);
- X return (1);
- X}
- X
- X
- Xstatic void
- Xload_hash()
- X{
- X register int i, c;
- X
- X bzero (Hash, sizeof(Hash));
- X for (i = 0; Find[i].search; ++i) {
- X c = *Find[i].search;
- X if (Hash[c] > 0)
- X Hash[c] = -Hash[c];
- X if (Hash[c] == 0)
- X Hash[c] = i | 0x100;
- X }
- X}
- X
- X
- Xvoid
- Xfree_entry()
- X{
- X free_table(0, NOHOLD);
- X Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry));
- X bzero (Entry[0].fields, sizeof(Entry[0].fields));
- X File_size = Entries = 0;
- X Entry->status = Entry->no = Entry->fpos = Current = 0;
- X Listsize = 3;
- X if (m_fi) {
- X fclose (m_fi);
- X m_fi = NULL;
- X }
- X}
- X
- X
- Xstatic void
- Xfree_table(at, hold)
- X{
- X int i, j;
- X
- X for (i = at; i < Entries; ++i) {
- X xfree (Entry[i].from);
- X for (j = 0; Find[j].search != NULL; ++j) {
- X if (Entry[i].fields[j] != quo_quo)
- X xfree (Entry[i].fields[j]);
- X }
- X }
- X Entries = (hold == HOLD) ? Entries : at;
- X File_size = (at) ? Entry[Entries].fpos : 0;
- X}
- X
- Xstatic
- Xsearch_from(fi)
- XFILE *fi;
- X{
- X while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
- X if (isfrom (Buf))
- X return (1);
- X }
- X return (0);
- X}
- X
- X
- Xsave_file(reload, mark, notmark)
- X{
- X FILE *fiscr;
- X int fdscr;
- X int new_size, i, count;
- X char scratch[64];
- X
- X for (i = 0; i < Entries; ++i) {
- X if ((Entry[i].status & mark) != mark ||
- X (~Entry[i].status & notmark) != notmark)
- X break;
- X }
- X if (i == Entries) {
- X m_select (Nulav, M_RESET);
- X puts ("No Changes Made");
- X return (Entries);
- X }
- X if (m_fi == NULL)
- X return (-1);
- X count = 0;
- X sprintf (scratch, "tmp:dmail%d", getpid());
- X do_flock (fileno(m_fi), LOCK_EX);
- X fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE);
- X#ifdef AMIGA /* fix bug in Lattice C fdopen */
- X fiscr = fopen("nil:", "w");
- X fclose(fiscr);
- X#endif
- X fiscr = fdopen (fdscr, "a+");
- X for (i = 0; i < Entries; ++i) {
- X if ((Entry[i].status & mark) == mark &&
- X (~Entry[i].status & notmark) == notmark) {
- X ++count;
- X fputs ("From ", fiscr);
- X fputs (Entry[i].from, fiscr);
- X putc ('\n', fiscr);
- X fseek (m_fi, Entry[i].fpos, 0);
- X while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
- X if (isfrom(Buf))
- X break;
- X fputs (Buf, fiscr);
- X }
- X }
- X }
- X
- X /* If NEW MAIL has come in, append that to the scratch file also */
- X
- X new_size = (fseek (m_fi, 0, 2) >= 0) ? ftell(m_fi) : File_size;
- X if (File_size != new_size) {
- X fseek (m_fi, File_size, 0);
- X while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL)
- X fputs (Buf, fiscr);
- X }
- X
- X /* Write scratch file back to mail file, or try to */
- X
- X fflush (fiscr);
- X fflush (m_fi);
- X
- X lseek (fdscr, 0 ,0);
- X#ifdef UNIX
- X lseek (fileno(m_fi), 0, 0);
- X while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
- X write (fileno(m_fi), Buf, i);
- X ftruncate (fileno(m_fi), lseek (fileno(m_fi), 0, 1));
- X#else
- X fclose(m_fi);
- X if (m_fi = fopen (mail_file, "w")) {
- X while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
- X write (fileno(m_fi), Buf, i);
- X fclose(m_fi);
- X m_fi = fopen (mail_file, "r+");
- X }
- X if (m_fi == NULL) {
- X printf("Unable to re-open %s !\n", mail_file);
- X return(-1);
- X }
- X#endif
- X if (lseek (fileno(m_fi), 0, 2) == 0 && !reload) {
- X if (Did_cd == 0) {
- X fclose(m_fi);
- X m_fi = NULL;
- X if (unlink (mail_file) == 0)
- X printf ("%s Removed\n", mail_file);
- X else
- X printf ("0 messages left in %s\n", mail_file);
- X }
- X }
- X fclose (fiscr);
- X if (m_fi)
- X fclose (m_fi); /* Effectively unlocks the descriptor */
- X m_fi = NULL;
- X unlink (scratch);
- X if (reload) {
- X free_entry();
- X load_mail(0, 0);
- X }
- X m_select (Nulav, M_RESET);
- X return (count);
- X}
- X
- Xvoid
- Xcheck_new_mail()
- X{
- X push_break();
- X if (m_fi == NULL) {
- X m_fi = fopen (mail_file, "r+");
- X if (m_fi == NULL) {
- X pop_break();
- X return;
- X }
- X }
- X if (fseek (m_fi, 0, 2) < 0 || ftell(m_fi) != File_size)
- X load_mail(Entries, 1);
- X pop_break();
- X}
- X
- X
- Xwrite_file(file, modes, mark, notmark)
- Xchar *file;
- X{
- X int i, fd = 1, notopen = 1;
- X FILE *fi = NULL;
- X
- X for (i = 0; i < Entries; ++i) {
- X if ((Entry[i].status & mark) == mark &&
- X (~Entry[i].status & notmark) == notmark) {
- X if (notopen) {
- X notopen = 0;
- X fd = open (file, O_APPEND | O_WRONLY | modes, MAILMODE);
- X if (fd < 0)
- X return (-1);
- X do_flock (fd, LOCK_EX);
- X#ifdef AMIGA /* fix bug in Lattice C fdopen */
- X fi = fopen("nil:", "w");
- X fclose(fi);
- X#endif
- X fi = fdopen (fd, "a");
- X
- X#ifdef NOTDEF
- X if (fi) {
- X printf("ptr %08lx\n", fi->_ptr);
- X printf("rcnt %08lx\n", fi->_rcnt);
- X printf("wcnt %08lx\n", fi->_wcnt);
- X printf("base %08lx\n", fi->_base);
- X printf("size %08lx\n", fi->_size);
- X printf("flag %08lx\n", fi->_flag);
- X printf("file %08lx\n", fi->_file);
- X return(-1);
- X }
- X#endif
- X }
- X fputs ("From ", fi);
- X fputs (Entry[i].from, fi);
- X putc ('\n', fi);
- X if (m_fi) {
- X fseek (m_fi, Entry[i].fpos, 0);
- X while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
- X if (isfrom(Buf))
- X break;
- X fputs (Buf, fi);
- X }
- X }
- X }
- X }
- X if (!notopen)
- X fclose (fi);
- X return (1);
- X}
- X
- X/*
- X * Basic scheme: Each entry has a fields list. Each entry in the fields list
- X * is guarenteed to be a valid malloc'd pointer (except some may be set to
- X * quo_quo).
- X *
- X * The find[] struct array holds the field name and length, the index
- X * corresponding to the index into the field[] in an Entry.
- X *
- X * The header and width arrays hold the list format.
- X */
- X
- Xget_extra_ovr(str)
- Xchar *str;
- X{
- X register int i;
- X
- X i = get_extra (str);
- X if (i < 0) {
- X i = add_extra (str);
- X load_changes();
- X }
- X return (i);
- X}
- X
- X
- X/*
- X * If there's room to add it, append to end.
- X * Else Find oldest field which doesn't exist in the setlist and replace it
- X * with the new one.
- X */
- X
- Xadd_extra(str)
- Xchar *str;
- X{
- X register int i, j, j_age, k;
- X
- X for (i = EXSTART; i < MAXTYPE; ++i) {
- X if (Find[i].search == NULL)
- X break;
- X ++Find[i].age;
- X }
- X if (i == MAXTYPE) { /* No room to add onto end */
- X j = j_age = -1;
- X for (i = EXSTART; i < MAXTYPE; ++i) {
- X for (k = 0; k < Listsize; ++k) {
- X if (i == header[k])
- X break;
- X }
- X if (k == Listsize && Find[i].age > j_age) {
- X j = i;
- X j_age = Find[i].age;
- X }
- X }
- X i = j;
- X }
- X if (i < 0)
- X return (-1);
- X push_break();
- X if (Find[i].search != NULL)
- X xfree (Find[i].search);
- X Find[i].len = strlen(str);
- X Find[i].search = malloc (Find[i].len + 1);
- X Find[i].notnew = Find[i].age = 0;
- X strcpy (Find[i].search, str);
- X changed = 1;
- X for (j = 0; j < Entries; ++j) {
- X if (Entry[j].fields[i] && Entry[j].fields[i] != quo_quo)
- X xfree (Entry[j].fields[i]);
- X Entry[j].fields[i] = quo_quo;
- X }
- X pop_break();
- X return (i);
- X}
- X
- X
- Xget_extra(str)
- Xchar *str;
- X{
- X int i;
- X
- X for (i = 0; Find[i].search; ++i) {
- X if (strncmp (str, Find[i].search, strlen(str)) == 0) {
- X Find[i].age = 0;
- X return (i);
- X }
- X }
- X return (-1);
- X}
- X
- X
- Xm_select(sav, mode)
- Xregister char *sav[];
- X{
- X char *ptr, *dest;
- X char l_map[256];
- X int idx[MAXLIST], ix = 0;
- X int ok, not, len, scr;
- X register int i, j, avi;
- X
- X for (i = 0;i < 256; ++i)
- X l_map[i] = i;
- X for (i = 'A'; i <= 'Z'; ++i)
- X l_map[i] += 'a' - 'A';
- X hold_load();
- X i = 0;
- X idx[ix++] = get_extra_ovr (sav[i++]);
- X for (; sav[i]; ++i) {
- X if (strcmp (sav[i], ",") == 0 && sav[i + 1])
- X idx[ix++] = get_extra_ovr (sav[++i]);
- X }
- X idx[ix] = -1;
- X nohold_load();
- X j = 1;
- X push_break();
- X for (i = 0; i < Entries; ++i) {
- X if (mode == M_CONT && Entry[i].no == 0)
- X continue;
- X ix = ok = 0;
- X avi = 1;
- X while ((ptr = sav[avi]) != NULL) {
- X if (ptr[0] == ',' && ptr[1] == '\0' && sav[avi+1]) {
- X ++ix;
- X avi += 2;
- X continue;
- X }
- X if (not = (*ptr == '!'))
- X ++ptr;
- X len = strlen (ptr);
- X dest = Entry[i].fields[idx[ix]];
- X if (*ptr == '\0') {
- X ok = 1;
- X goto gotit;
- X }
- X while (*dest) {
- X scr = 0;
- X while (l_map[dest[scr]] == l_map[ptr[scr]] && ptr[scr])
- X ++scr;
- X if (ptr[scr] == '\0') {
- X ok = 1;
- X goto gotit;
- X }
- X ++dest;
- X }
- X ++avi;
- X }
- Xgotit:
- X Entry[i].no = (ok ^ not) ? j++ : 0;
- X }
- X pop_break();
- X if (Current < 0)
- X Current = 0;
- X if (Entries) {
- X if (Entry[Current].no == 0) {
- X Current = indexof (1);
- X if (Current < 0) {
- X Current = 0;
- X return (-1);
- X }
- X }
- X } else {
- X Current = -1;
- X }
- X return (1);
- X}
- X
- X
- END_OF_FILE
- if test 13593 -ne `wc -c <'src/dmail/load_mail.c'`; then
- echo shar: \"'src/dmail/load_mail.c'\" unpacked with wrong size!
- fi
- # end of 'src/dmail/load_mail.c'
- fi
- if test -f 'src/uucico/gio.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/uucico/gio.c'\"
- else
- echo shar: Extracting \"'src/uucico/gio.c'\" \(16481 characters\)
- sed "s/^X//" >'src/uucico/gio.c' <<'END_OF_FILE'
- X
- X/*
- X * GIO.C WINDOWED G PROTOCOL
- X *
- X * Rewritten from scratch, except the checksum routine which was
- X * rewritten but based on the old one.
- X *
- X * WINDOW SIZE: When changing the window size be sure there
- X * are enough buffers available for pending txs.
- X *
- X * GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
- X */
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <exec/types.h>
- X#include <proto/all.h>
- X
- Xvoid FrameToPacket();
- X
- Xextern int debug;
- Xextern int WindowOne;
- X
- X#define SUCCESS 0
- X#define FAIL 1
- X
- X#define MAGIC 0125252
- X#define DLE 0x10
- X#define WINDOWSIZE 2 /* WindowSize = 1 or 2 */
- X#define SEGSIZEK 2 /* 64 bytes ?? */
- X
- X#define SUB1(var) (((var)-1)&7)
- X
- Xtypedef unsigned char ubyte;
- Xtypedef unsigned short uword;
- X
- Xtypedef struct {
- X ubyte Dle; /* Literal ASCII DLE */
- X ubyte K; /* data size 2^(K+4) except K=0 means no data */
- X ubyte CL,CH; /* MAGIC - chksum(data) ^ C */
- X ubyte C;
- X ubyte X; /* K ^ C0 ^ C1 ^ C */
- X} Frame;
- X
- Xtypedef struct {
- X ubyte CType; /* bits 7-6 of C */
- X ubyte CCmd; /* bits 5-3 of C */
- X ubyte CSeq; /* bits 2-0 of C */
- X ubyte PLen; /* pre-data (2 bytes) for SHORTDATA type */
- X ubyte *Data; /* implies CType=LONGDATA or SHORTDATA */
- X uword DLen; /* length of data */
- X} Packet;
- X
- X#define CT_CONTROL (0 << 6)
- X#define CT_ALTCHN (1 << 6)
- X#define CT_LONGDATA (2 << 6)
- X#define CT_SHORTDATA (3 << 6)
- X#define CT_MASK (3 << 6)
- X
- X#define CC_CLOSE (1 << 3)
- X#define CC_RJ (2 << 3)
- X#define CC_SRJ (3 << 3)
- X#define CC_RR (4 << 3)
- X#define CC_INITC (5 << 3)
- X#define CC_INITB (6 << 3)
- X#define CC_INITA (7 << 3)
- X#define CC_MASK (7 << 3)
- X
- X#define SEQ_MASK 7
- X
- X#define WAIT_ACK 1
- X#define WAIT_DATA 2
- X#define WAIT_CONTROL 3
- X
- X#define MaxPktSize 4096
- X
- Xchar RxBuf[MaxPktSize+4];
- Xchar TxBuf[4][MaxPktSize+4];
- X
- X /* TRANSMIT STAGE */
- Xchar TxSeq = 0; /* Last send packet */
- Xchar TxPend= 0; /* hasn't been acked yet */
- Xuword TxWinSize; /* 1 or 2 */
- Xuword TxSegSize; /* maximum segment size */
- Xchar TxSegK; /* K for TxSegSize */
- XPacket TxPacket[8]; /* contents of last packet */
- X
- X /* RECEIVE STAGE */
- Xchar RxSeq = 1; /* Next expected recv pkt */
- Xchar RxRdy = 0; /* Has come in.. */
- Xchar RxRetry = 4;
- Xchar RxNotAcked = 0; /* We have yet to ack it */
- XPacket RxPacket; /* The packet that has come in */
- X
- X/*
- X * Get Transmit Buffer. Note that some space to the left is available
- X */
- X
- Xchar *
- XGetTxBuf()
- X{
- X static int index = 0;
- X
- X index = (index + 1) & 3;
- X return(TxBuf[index] + 2);
- X}
- X
- Xint
- Xgwrdata(fi)
- XFILE *fi;
- X{
- X int bytes;
- X char *buf = GetTxBuf();
- X
- X if (debug > 7)
- X printf("GWRDATA: ");
- X
- X while ((bytes = fread(buf, 1, TxSegSize, fi)) >= 0) {
- X if (SendDataPacket(buf, bytes) != SUCCESS) {
- X if (debug > 7)
- X printf("GWR Failed\n");
- X return(FAIL);
- X }
- X if (debug > 7)
- X printf("\nGWROK ");
- X if (bytes == 0)
- X break;
- X buf = GetTxBuf();
- X }
- X if (debug > 7)
- X printf("\nGWFile Last Ack\n");
- X while (TxPend) {
- X if (GetData(WAIT_ACK, NULL) == FAIL)
- X return(FAIL);
- X }
- X return (SUCCESS);
- X}
- X
- X/*
- X * Write message to the other guy.
- X *
- X * NOTE: LONGDATA packets used exclusively and \0 fill to end.
- X */
- X
- Xint
- Xgwrmsg(str)
- Xchar *str;
- X{
- X int len = strlen(str) + 1; /* type + str + \0 */
- X
- X if (debug > 8)
- X printf("GWRMSG: %s\n", str);
- X
- X while (len > TxSegSize) {
- X char *buf = GetTxBuf();
- X movmem(str, buf, TxSegSize);
- X if (debug > 8)
- X printf("GWR-SEND %d\n", TxSegSize);
- X if (SendDataPacket(buf, TxSegSize) != SUCCESS)
- X return(FAIL);
- X len -= TxSegSize;
- X str += TxSegSize;
- X }
- X
- X /*
- X * Find optimal packet size (remember, we must force LONGDATA
- X *
- X * Apparently packet sizes less than the agreed upon size are
- X * not allowed ???
- X */
- X
- X {
- X short siz = TxSegSize;
- X char *buf = GetTxBuf();
- X#ifdef NOTDEF
- X short k = TxSegK;
- X
- X while (k > 1 && (siz >> 1) >= len) {
- X --k;
- X siz >>= 1;
- X }
- X#endif
- X if (debug > 8)
- X printf("GWR-FNL %d %d\n", len, siz);
- X
- X movmem(str, buf, len);
- X setmem(buf + len, siz - len, 0);
- X if (SendDataPacket(buf, siz) != SUCCESS) {
- X if (debug > 8)
- X printf("GWR-FAIL\n");
- X return(FAIL);
- X }
- X }
- X if (debug > 8)
- X printf("GWR Last Ack\n");
- X while (TxPend) {
- X if (GetData(WAIT_ACK, NULL) == FAIL)
- X return(FAIL);
- X }
- X return (SUCCESS);
- X}
- X
- Xint
- Xgrddata(fi)
- XFILE *fi;
- X{
- X int bytes;
- X char *buf;
- X
- X if (debug > 7)
- X printf("GRDDATA\n");
- X while ((bytes = RecvDataPacket(&buf)) > 0) {
- X if (debug > 7)
- X printf("GRDDATA blk %d\n", bytes);
- X fwrite(buf, 1, bytes, fi);
- X }
- X if (debug > 7)
- X printf("GRDDATA end %d\n", bytes);
- X if (bytes < 0)
- X return(FAIL);
- X else
- X return(SUCCESS);
- X}
- X
- Xgrdmsg(buf, maxlen)
- Xchar *buf;
- X{
- X short i;
- X short n;
- X short slen;
- X char *ptr;
- X
- X i = 0;
- X if (debug > 8)
- X printf("GRDMSG\n");
- X while ((n = RecvDataPacket(&ptr)) > 0) {
- X ptr[n] = 0;
- X slen = strlen(ptr);
- X if (slen > maxlen - 1) {
- X printf("GRDMSG: Buffer overflow!\n");
- X return (FAIL);
- X }
- X movmem(ptr, buf + i, slen);
- X buf[i + slen] = 0;
- X if (slen != n)
- X break;
- X i += slen;
- X maxlen -= slen;
- X }
- X if (debug > 8)
- X printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
- X if (n < 0) {
- X buf[0] = 0;
- X return(FAIL);
- X }
- X return(SUCCESS);
- X}
- X
- XSendDataPacket(buf, bytes)
- Xubyte *buf;
- Xint bytes;
- X{
- X Packet P;
- X
- X /*
- X * If window exhausted we must wait for at least one ack.
- X */
- X
- X if (TxPend == TxWinSize) {
- X if (GetData(WAIT_ACK, NULL) == FAIL)
- X return(FAIL);
- X }
- X
- X TxSeq = (TxSeq + 1) & 7; /* next Tx packet */
- X
- X /*
- X * Figure out best fit packet size. Apparently packets smaller
- X * then the agreed upon size are not allowed ???
- X */
- X
- X#ifdef NOTDEF
- X {
- X short k = TxSegK;
- X P.DLen = TxSegSize;
- X while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
- X --k;
- X P.DLen >>= 1;
- X }
- X }
- X#else
- X P.DLen = TxSegSize;
- X#endif
- X
- X if (bytes < P.DLen) {
- X uword extra = P.DLen - bytes;
- X setmem(buf + bytes, extra, 0);
- X if (extra <= 127) {
- X P.PLen = 1;
- X buf[-1] = extra;
- X } else {
- X P.PLen = 2;
- X buf[-2] = 0x80 | extra;
- X buf[-1] = (extra >> 7);
- X }
- X P.CType = CT_SHORTDATA;
- X } else {
- X P.PLen = 0;
- X P.CType = CT_LONGDATA;
- X }
- X P.CCmd = TxSeq << 3; /* transmit sequence number */
- X P.CSeq = (RxSeq - 1) & 7; /* last valid received pkt */
- X P.Data = buf;
- X
- X if (debug > 8)
- X printf("WRITE PACKET %d %d\n", TxSeq, P.CSeq);
- X
- X if (RxNotAcked) /* We've acked the rx packet */
- X RxNotAcked = 0;
- X
- X TxPacket[TxSeq & 7] = P;
- X ++TxPend;
- X
- X WritePacket(&TxPacket[TxSeq & 7], 1);
- X
- X return(SUCCESS);
- X}
- X
- XRecvDataPacket(pbuf)
- Xchar **pbuf;
- X{
- X if (RxRdy == 0) {
- X if (GetData(WAIT_DATA, NULL) != SUCCESS)
- X return(-1);
- X }
- X *pbuf = RxPacket.Data;
- X RxRdy = 0;
- X return((int)RxPacket.DLen);
- X}
- X
- Xgturnon(master)
- X{
- X Packet P;
- X short retry = 5;
- X short windowsize = WINDOWSIZE; /* our prefered window size */
- X short segsize = SEGSIZEK; /* our prefered segment size */
- X
- X if (WindowOne)
- X windowsize = 1;
- X
- X if (master) {
- X while (retry > 0) {
- X WriteCtlPacket(CC_INITA | windowsize);
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
- X if (P.CSeq && P.CSeq < windowsize)
- X windowsize = P.CSeq;
- X break;
- X }
- X --retry;
- X }
- X while (retry > 0) {
- X WriteCtlPacket(CC_INITB | (segsize - 1));
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
- X if (P.CSeq < segsize - 1)
- X segsize = P.CSeq + 1;
- X break;
- X }
- X --retry;
- X }
- X while (retry > 0) {
- X WriteCtlPacket(CC_INITC | windowsize);
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
- X if (P.CSeq && P.CSeq < windowsize)
- X windowsize = P.CSeq;
- X break;
- X }
- X --retry;
- X }
- X } else {
- X while (retry > 0) {
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
- X WriteCtlPacket(CC_INITA | windowsize);
- X if (P.CSeq && windowsize > P.CSeq)
- X windowsize = P.CSeq;
- X break;
- X }
- X --retry;
- X }
- X while (retry > 0) {
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
- X WriteCtlPacket(CC_INITB | (segsize - 1));
- X if (P.CSeq < segsize - 1)
- X segsize = P.CSeq + 1;
- X break;
- X }
- X --retry;
- X }
- X while (retry > 0) {
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
- X WriteCtlPacket(CC_INITC | windowsize);
- X if (P.CSeq && windowsize > P.CSeq)
- X windowsize = P.CSeq;
- X break;
- X }
- X --retry;
- X }
- X }
- X TxSegK = segsize;
- X TxSegSize = 1 << (TxSegK + 4);
- X TxWinSize = windowsize;
- X if (debug > 0)
- X printf("Window Size is %d\n", TxWinSize);
- X if (retry == 0)
- X return(FAIL);
- X return(SUCCESS);
- X}
- X
- Xgturnoff()
- X{
- X Packet P;
- X
- X WriteCtlPacket(CC_CLOSE);
- X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) {
- X WriteCtlPacket(CC_RR | ((RxSeq - 1) & 7));
- X return (SUCCESS);
- X }
- X return (FAIL);
- X}
- X
- XGetData(waitfor, p)
- XPacket *p;
- X{
- X Packet P;
- X short timeout;
- X
- X /*
- X * If we haven't acked the last packet we received we must do
- X * so now before we can expect to receive another one!
- X */
- X
- X if (waitfor == WAIT_ACK)
- X timeout = 20;
- X else if (waitfor == WAIT_DATA)
- X timeout = 40;
- X else
- X timeout = 40;
- X
- X for (;;) {
- X if (RxNotAcked) {
- X WriteCtlPacket(CC_RR | SUB1(RxSeq));
- X RxNotAcked = 0;
- X }
- X if (ReadPacket(&P, timeout) == FAIL) {
- X if (waitfor == WAIT_DATA) {
- X if (RxRetry) {
- X --RxRetry;
- X if (debug > 8)
- X printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
- X WriteCtlPacket(CC_RJ | SUB1(RxSeq));
- X continue;
- X }
- X }
- X if (waitfor == WAIT_ACK) {
- X if (RxRetry) {
- X --RxRetry;
- X if (debug > 8)
- X printf("\nWAIT-ACK, TIMEOUT, RETRY\n");
- X WritePacket(&TxPacket[(TxSeq - TxPend + 1) & 7], 1);
- X continue;
- X }
- X }
- X if (debug > 8)
- X printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
- X return(FAIL);
- X }
- X RxRetry = 4;
- X switch(P.CType) {
- X case CT_CONTROL:
- X switch(P.CCmd) {
- X case CC_CLOSE: /* End of communication ... not an ACK! */
- X if (waitfor == WAIT_CONTROL) {
- X *p = P;
- X return(SUCCESS);
- X }
- X return(FAIL);
- X case CC_RJ: /* Reject packet (P.CSeq == last good packet) */
- X /* resend last packet */
- X
- X WritePacket(&TxPacket[(P.CSeq + 1) & 7], 1);
- X {
- X short i;
- X for (i = 0; i < TxPend; ++i) {
- X if (P.CSeq == ((TxSeq - i) & 7))
- X break;
- X }
- X if (i == TxPend)
- X printf("RJ, bad seq no: %d expected %d-%d\n", P.CSeq, (TxSeq - TxPend + 1) & 7, TxSeq);
- X }
- X break;
- X case CC_SRJ: /* Selective Reject (P.CSeq == bad packet # ) */
- X return(FAIL);
- X case CC_RR: /* Ack to packet (P.CSeq == packet # acked) */
- X if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
- X return(SUCCESS);
- X break;
- X case CC_INITC:
- X case CC_INITB:
- X case CC_INITA:
- X if (waitfor == WAIT_CONTROL) {
- X *p = P;
- X return(SUCCESS);
- X }
- X return(FAIL);
- X }
- X break;
- X case CT_ALTCHN:
- X printf("ALTCHN packet ??\n");
- X break;
- X case CT_LONGDATA:
- X case CT_SHORTDATA:
- X {
- X char rxseq = P.CCmd >> 3;
- X char txack = P.CSeq;
- X
- X if (RxRdy == 1) {
- X printf("Got two receive packets without me acking!\n");
- X }
- X if (rxseq == SUB1(RxSeq)) {
- X RxNotAcked = 1;
- X continue; /* ignore resent pkts we already have */
- X } else if (rxseq != RxSeq) {
- X if (rxseq == ((RxSeq + 1) & 7)) /* missed one (windowed) */
- X WriteCtlPacket(CC_RJ | SUB1(RxSeq));
- X printf("Received sequence %d, expected %d\n", rxseq, RxSeq);
- X break;
- X } else {
- X if (debug > 6)
- X printf("RECV SEQUENCE %d\n", rxseq);
- X }
- X
- X RecvdAck(txack);
- X
- X /*
- X * Delay sending the ACK back in case we can combine
- X * it with the next transmitted packet.
- X */
- X
- X RxNotAcked = 1; /* we haven't ack'd the rx packet */
- X
- X RxSeq = (RxSeq + 1) & 7;
- X RxRdy = 1;
- X RxPacket = P;
- X if (waitfor == WAIT_DATA)
- X return(SUCCESS);
- X if (TxPend == 0 && waitfor == WAIT_ACK)
- X return(SUCCESS);
- X }
- X break;
- X }
- X }
- X}
- X
- XRecvdAck(seq)
- Xchar seq;
- X{
- X short i;
- X short seqbase = TxSeq - TxPend + 1;
- X
- X /*
- X * which packet was acked?
- X */
- X
- X for (i = 0; i < TxPend; ++i) {
- X if (seq == ((seqbase + i) & 7))
- X break;
- X }
- X if (i == TxPend) {
- X if (TxPend)
- X printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
- X return(FAIL);
- X }
- X if (debug > 8)
- X printf("TxPend %d ->", TxPend);
- X TxPend = TxPend - i - 1;
- X if (debug > 8)
- X printf(" %d\n", TxPend);
- X return(SUCCESS);
- X}
- X
- XWriteCtlPacket(cc)
- X{
- X Packet pk;
- X
- X pk.CType = CT_CONTROL;
- X pk.CCmd = cc & CC_MASK;
- X pk.CSeq = cc & SEQ_MASK;
- X pk.PLen = 0;
- X pk.DLen = 0;
- X WritePacket(&pk, 0);
- X return(SUCCESS);
- X}
- X
- XWritePacket(pk, async)
- XPacket *pk;
- X{
- X Frame F;
- X uword sum;
- X
- X F.Dle = DLE;
- X F.C = pk->CType | pk->CCmd | pk->CSeq;
- X F.K = 9;
- X
- X if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
- X F.K = LenToK(pk->DLen);
- X else
- X pk->DLen = 0;
- X
- X sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
- X
- X F.CH = sum >> 8;
- X F.CL = sum;
- X F.X = F.K ^ F.CH ^ F.CL ^ F.C;
- X
- X if (debug > 8)
- X printf("WritePacket: F.K = %d F.C = %02x\n", F.K, F.C);
- X
- X if (async)
- X xwritea(&F, sizeof(F));
- X else
- X xwrite(&F, sizeof(F)); /* write header */
- X if (pk->DLen) { /* write data */
- X if (async)
- X xwritea(pk->Data - pk->PLen, pk->DLen);
- X else
- X xwrite(pk->Data - pk->PLen, pk->DLen);
- X }
- X return(SUCCESS);
- X}
- X
- XReadPacket(pk, timeout)
- XPacket *pk;
- X{
- X Frame F;
- X short c;
- X short i = 0;
- X
- X pk->Data = RxBuf;
- X pk->CType = 0xFF;
- X pk->CCmd = 0;
- X pk->CSeq = 0;
- X
- X if (debug > 8)
- X printf("ReadPacket\n");
- X while ((c = xgetc(timeout)) != EOF) {
- X if (debug > 8)
- X printf("RP %d %02x\n", i, c);
- X
- X switch(i) {
- X case 0:
- X if (c == DLE) {
- X F.Dle = c;
- X ++i;
- X }
- X break;
- X case 1:
- X F.K = c;
- X ++i;
- X if (c == DLE) { /* K only valid 0-9 */
- X F.Dle = c;
- X i = 1;
- X }
- X break;
- X case 2:
- X F.CL = c;
- X ++i;
- X break;
- X case 3:
- X F.CH = c;
- X ++i;
- X break;
- X case 4:
- X F.C = c;
- X ++i;
- X break;
- X case 5:
- X F.X = c;
- X if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
- X printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
- X i = 0;
- X } else { /* get data segment if any */
- X ++i;
- X }
- X break;
- X }
- X if (i == 6)
- X break;
- X }
- X if (debug > 8)
- X printf("RP Hdr i = %d, F.K = %d F.C = %02x\n", i, F.K, F.C);
- X
- X if (i == 6) { /* Receive Data Portion */
- X uword pktsize = 1 << (F.K + 4);
- X uword n;
- X
- X if (F.K == 0 || F.K == 9)
- X pktsize = 0; /* FIXME is K=0 an illegal case? */
- X
- X if (pktsize > MaxPktSize) {
- X printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
- X return (FAIL);
- X }
- X for (n = 0; n < pktsize; ++n) {
- X if ((c = xgetc(4)) == EOF)
- X break;
- X pk->Data[n] = c;
- X }
- X if (c != EOF) {
- X uword hissum;
- X uword oursum;
- X hissum = (F.CH << 8) | F.CL;
- X oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
- X if (debug > 8)
- X printf("Got Data, checking: %04x %04x\n", hissum, oursum);
- X if (hissum == oursum) {
- X FrameToPacket(&F, pk, pk->Data);
- X return (SUCCESS);
- X }
- X } else {
- X FrameToPacket(&F, pk, pk->Data); /* mainly for pk->CType */
- X return (FAIL);
- X }
- X }
- X /*
- X * Timeout, retry?
- X */
- X return (FAIL);
- X}
- X
- XCheckSum(s, n)
- Xubyte *s;
- Xint n;
- X{
- X uword sum;
- X uword x;
- X uword t;
- X
- X if (n == 0)
- X return(0);
- X sum = -1;
- X x = 0;
- X
- X while (n) {
- X if (sum & 0x8000)
- X sum = (sum << 1) | 1;
- X else
- X sum = (sum << 1);
- X
- X t = sum;
- X sum += *s++;
- X x += sum ^ n;
- X if (sum <= t)
- X sum ^= x;
- X --n;
- X }
- X return((int)sum);
- X}
- X
- Xvoid
- XFrameToPacket(fr, pk, data)
- XFrame *fr;
- XPacket *pk;
- Xubyte *data;
- X{
- X pk->CType = fr->C & CT_MASK;
- X pk->CCmd = fr->C & CC_MASK;
- X pk->CSeq = fr->C & SEQ_MASK;
- X switch(pk->CType) {
- X case CT_LONGDATA:
- X pk->DLen = 1 << (fr->K + 4);
- X break;
- X case CT_SHORTDATA:
- X pk->DLen = 1 << (fr->K + 4);
- X if (pk->Data[0] & 0x80) {
- X pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
- X if (pk->DLen < 0) {
- X printf("DLEN ERROR %d\n", pk->DLen);
- X pk->DLen = 0;
- X }
- X pk->Data += 2;
- X } else {
- X pk->DLen -= *pk->Data;
- X ++pk->Data;
- X }
- X break;
- X default:
- X pk->DLen = 0;
- X break;
- X }
- X}
- X
- XLenToK(bytes)
- Xuword bytes;
- X{
- X uword n = 32;
- X uword k = 1;
- X
- X while (n < bytes) {
- X n <<= 1;
- X ++k;
- X }
- X if (k > 8) {
- X printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
- X k = 8;
- X }
- X return((int)k);
- X}
- X
- END_OF_FILE
- if test 16481 -ne `wc -c <'src/uucico/gio.c'`; then
- echo shar: \"'src/uucico/gio.c'\" unpacked with wrong size!
- fi
- # end of 'src/uucico/gio.c'
- fi
- echo shar: End of archive 8 \(of 16\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions should be addressed to ``amiga-request''
- (please only use ``amiga'' for actual submissions) at the above addresses.
-